/*            Copyright(c) 2006-2008 Dave Sexton           *
 * http://www.codeplex.com/DocProject                      *
 * http://www.codeplex.com/DocProject/Project/License.aspx *
 ***********************************************************/
using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using DaveSexton.DocProject.Sandcastle.TopicManagement;

namespace DaveSexton.DocProject.Sandcastle.ContentManagement
{
	[Serializable]
	public sealed class XmlCommentSection : ITopicSection
	{
		#region Public Properties
		public bool IsCustom
		{
			get
			{
				return isCustom;
			}
		}

		public ContentItemEditModes EditModes
		{
			get
			{
				return editModes;
			}
		}

		public string Name
		{
			get
			{
				return name;
			}
		}

		public bool AllowMultiplePerTopic
		{
			get
			{
				return multiple;
			}
		}

		public bool IsMarkerOnly
		{
			get
			{
				return marker;
			}
		}

		public ICollection<ITopicSectionAttributeData> Attributes
		{
			get
			{
				return attributes.AsReadOnly();
			}
		}

		public ICollection<string> Subsections
		{
			get
			{
				return subsections.AsReadOnly();
			}
		}
		#endregion

		#region Private / Protected
		private readonly string name;
		private readonly ContentItemEditModes editModes;
		private readonly bool multiple, marker, isCustom;
		private readonly List<ITopicSectionAttributeData> attributes = new List<ITopicSectionAttributeData>(0);
		private readonly List<TopicType> appliesTo = new List<TopicType>(4);
		private readonly List<string> subsections = new List<string>(0);
		#endregion

		#region Constructors
		/// <summary>
		/// Constructs a new instance of the <see cref="XmlCommentSection" /> class.
		/// </summary>
		public XmlCommentSection(string name, bool isCustom, IEnumerable<ITopicSectionAttributeData> attributes, bool multiple, bool marker, 
			IEnumerable<TopicType> appliesTo, ContentItemEditModes editModes, IEnumerable<string> subsections)
		{
			if (string.IsNullOrEmpty(name))
				throw new ArgumentException(Resources.Errors.NullOrEmpty, "name");

			if (appliesTo == null)
				throw new ArgumentNullException("appliesTo");

			if (attributes != null)
				this.attributes.AddRange(attributes);

			this.name = name;
			this.isCustom = isCustom;
			this.multiple = multiple;
			this.marker = marker;
			this.appliesTo.AddRange(appliesTo);
			this.editModes = editModes;

			if (subsections != null)
				this.subsections.AddRange(subsections);
		}

		/// <summary>
		/// Constructs a new instance of the <see cref="XmlCommentSection" /> class.
		/// </summary>
		public XmlCommentSection(XmlCommentSection clone)
		{
			if (clone == null)
				throw new ArgumentNullException("clone");

			name = clone.name;
			multiple = clone.multiple;
			marker = clone.marker;
			editModes = clone.editModes;
			appliesTo.AddRange(clone.appliesTo);
			subsections.AddRange(clone.subsections);

			foreach (ITopicSectionAttributeData attribute in clone.attributes)
				attributes.Add(new XmlCommentSectionAttributeData(attribute.Name, attribute.AttributeType));
		}
		#endregion

		#region Methods
		public static XmlCommentSection CreateCustom(string name)
		{
			return CreateCustom(name, null);
		}

		public static XmlCommentSection CreateCustom(string name, IEnumerable<ITopicSectionAttributeData> attributes)
		{
			List<TopicType> appliesTo = new List<TopicType>(6);
			appliesTo.Add(TopicType.General);
			appliesTo.Add(TopicType.Project);
			appliesTo.Add(TopicType.Namespace);
			appliesTo.Add(TopicType.Module);
			appliesTo.Add(TopicType.Type);
			appliesTo.Add(TopicType.Member);

			return new XmlCommentSection(System.Xml.XmlConvert.EncodeName(name),
				true, attributes, true, false, appliesTo, ContentItemEditModes.Source | ContentItemEditModes.Design, null);
		}

		public bool AppliesTo(TopicType type)
		{
			switch (type)
			{
				case TopicType.Class:
				case TopicType.Delegate:
				case TopicType.Enum:
				case TopicType.Interface:
				case TopicType.Structure:
					if (appliesTo.Contains(TopicType.Type))
						return true;

					goto default;
				case TopicType.Event:
				case TopicType.Field:
				case TopicType.Method:
				case TopicType.Property:
					if (appliesTo.Contains(TopicType.Member))
						return true;

					goto default;
				default:
					return appliesTo.Contains(type);
			}
		}

		public override string ToString()
		{
			return name;
		}
		#endregion
	}
}
